﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Quick_Match_Game
{
    class playingGame
    {
        List<string> TypesOfCards = new List<string>(); List<string> CardsRandom = new List<string>(); List<string> Pile = new List<string>(); Random R = new Random();
        playingGame[] Players; int NumberOfPlayers; string Name; List<string> Deck = new List<string>(); string DiscardedCard; string PrecedentPlayerName;
        List<string> CardSuits = new List<string>();

        internal void setTypes()
        {
            TypesOfCards.Add("The Ace of Clubs"); TypesOfCards.Add("The Two of Clubs"); TypesOfCards.Add("The Three of Clubs"); TypesOfCards.Add("The Four of Clubs"); TypesOfCards.Add("The Five of Clubs"); TypesOfCards.Add("The Six of Clubs"); TypesOfCards.Add("The Seven of Clubs"); TypesOfCards.Add("The Eight of Clubs"); TypesOfCards.Add("The Nine of Clubs"); TypesOfCards.Add("The Ten of Clubs"); TypesOfCards.Add("The Jack of Clubs"); TypesOfCards.Add("The Queen of Clubs"); TypesOfCards.Add("The King of Clubs");
            TypesOfCards.Add("The Ace of Diamonds"); TypesOfCards.Add("The Two of Diamonds"); TypesOfCards.Add("The Three of Diamonds"); TypesOfCards.Add("The Four of Diamonds"); TypesOfCards.Add("The Five of Diamonds"); TypesOfCards.Add("The Six of Diamonds"); TypesOfCards.Add("The Seven of Diamonds"); TypesOfCards.Add("The Eight of Diamonds"); TypesOfCards.Add("The Nine of Diamonds"); TypesOfCards.Add("The Ten of Diamonds"); TypesOfCards.Add("The Jack of Diamonds"); TypesOfCards.Add("The Queen of Diamonds"); TypesOfCards.Add("The King of Diamonds");
            TypesOfCards.Add("The Ace of Hearts"); TypesOfCards.Add("The Two of Hearts"); TypesOfCards.Add("The Three of Hearts"); TypesOfCards.Add("The Four of Hearts"); TypesOfCards.Add("The Five of Hearts"); TypesOfCards.Add("The Six of Hearts"); TypesOfCards.Add("The Seven of Hearts"); TypesOfCards.Add("The Eight of Hearts"); TypesOfCards.Add("The Nine of Hearts"); TypesOfCards.Add("The Ten of Hearts"); TypesOfCards.Add("The Jack of Hearts"); TypesOfCards.Add("The Queen of Hearts"); TypesOfCards.Add("The King of Hearts");
            TypesOfCards.Add("The Ace of Spades"); TypesOfCards.Add("The Two of Spades"); TypesOfCards.Add("The Three of Spades"); TypesOfCards.Add("The Four of Spades"); TypesOfCards.Add("The Five of Spades"); TypesOfCards.Add("The Six of Spades"); TypesOfCards.Add("The Seven of Spades"); TypesOfCards.Add("The Eight of Spades"); TypesOfCards.Add("The Nine of Spades"); TypesOfCards.Add("The Ten of Spades"); TypesOfCards.Add("The Jack of Spades"); TypesOfCards.Add("The Queen of Spades"); TypesOfCards.Add("The King of Spades");
            CardSuits.Add("Clubs"); CardSuits.Add("Diamonds"); CardSuits.Add("Hearts"); CardSuits.Add("Spades");
            this.buildPile();
        }
        internal void buildPile()
        {
            int rgn = 0; CardsRandom = TypesOfCards; int crs=0;
            for (int i = 0; i < 52; i++)
            {
                crs=CardsRandom.Count-1; rgn = R.Next(0, crs); Pile.Add(CardsRandom[rgn]); CardsRandom.RemoveAt(rgn);
            }
            this.welcomeScreen();
        }
        void welcomeScreen()
        {
            Console.Clear();
            Console.WriteLine("\t\t\tQuick Match"); Console.WriteLine("\nThe first player to collect five cards of the same suit wins the game.\n"); this.acceptUsers();
        }
        internal void acceptUsers()
        {
            while (true)
            {
                try
                {
                    Console.Write("Enter the number of players (2-4): "); NumberOfPlayers = Convert.ToInt32(Console.ReadLine()); Players = new playingGame[NumberOfPlayers];
                    if (NumberOfPlayers == 2 || NumberOfPlayers == 3 || NumberOfPlayers == 4)
                    {
                        for (int i = 0; i < NumberOfPlayers; i++)
                        {
                            Players[i] = new playingGame(); Console.Write("Player {0} Name: ", i + 1); Players[i].Name = Console.ReadLine();
                        }
                        break;
                    }
                    else { throw new FormatException(); }
                }
                catch (FormatException)
                {
                    Console.WriteLine("\nWrong input you are to enter a number from 2 to 4 and names of players !\n");
                }
            }
            this.distribution();
        }
        internal void distribution()
        {
            int rgn = 0; int crs=0;
            for (int i = 0; i < NumberOfPlayers; i++)
            {
                for (int n = 0; n < 5; n++)
                {
                    crs = Pile.Count - 1; rgn = R.Next(0, crs); Players[i].Deck.Add(Pile[rgn]); Pile.RemoveAt(rgn);
                }
            } 
            this.firstMove();
        }
        void firstMove()
        {
            char btn = 'z'; int crs;
            while (true)
            {
                try
                {
                    this.displayDeck(Players, 0);
                    Console.Write("\nPress D to draw a card from pile "); btn = Convert.ToChar(Console.ReadLine());
                    if (btn == 'D' || btn == 'd')
                    {
                        crs = Pile.Count - 1; Players[0].Deck.Add(Pile[crs]); Pile.RemoveAt(crs); break;
                    }
                    else { throw new FormatException(); }
                }
                catch (FormatException)
                {
                    Console.WriteLine("\nWrong input, you are to press D !\n");
                }
            }
            this.displayDeckNumbered(Players, 0); this.discardCard(Players, 0); this.checkWinningSuit(Players, 0); this.gamePlay();
        }
        void displayDeck(playingGame[] plyr,int idx)
        {
            Console.WriteLine("\n{0}'s turn\n",Players[idx].Name);
            for (int i = 0; i < plyr[idx].Deck.Count; i++)
            {
                Console.WriteLine(plyr[idx].Deck[i]);
            } return;
        }
        void displayDeckNumbered(playingGame[] plyr, int idx)
        {
            Console.WriteLine();
            for (int i = 0; i < plyr[idx].Deck.Count; i++)
            {
                Console.WriteLine("{0}. {1}",i+1,plyr[idx].Deck[i]);
            } return;
        }
        void discardCard(playingGame[] plyr, int idx)
        {
            while (true)
            {
                int dC = 0;
                try
                {
                    Console.Write("\nEnter the card number to be discarded (1-6): "); dC = Convert.ToInt32(Console.ReadLine());
                    if (dC == 1 || dC == 2 || dC == 3 || dC == 4 || dC == 5 || dC == 6)
                    {
                        dC--; DiscardedCard = plyr[idx].Deck[dC]; plyr[idx].Deck.RemoveAt(dC);
                        Console.WriteLine("\nCard discarded is " + DiscardedCard); PrecedentPlayerName = plyr[idx].Name; break;
                    }
                    else { throw new FormatException(); }
                }
                catch (FormatException)
                {
                    Console.WriteLine("\nWrong input, you must enter a number from 1 through 6 !\n");
                }
            } return;
        }
        void pickDiscarded(playingGame[] plyr, int idx)
        {
            plyr[idx].Deck.Add(DiscardedCard); return;
        }
        void drawPile(playingGame[] plyr, int idx)
        {
            int crs = 0; crs = Pile.Count - 1; plyr[idx].Deck.Add(Pile[crs]); Pile.RemoveAt(crs); return;
        }
        internal void gamePlay()
        {
            bool afp = true; int i = 0; char btn = 'z';
            while (true)
            {
                if (afp == true) { i = 1; } else { i = 0; }
                for (; i < NumberOfPlayers; i++)
                {
                    while (true)
                    {
                        try
                        {
                            this.displayDeck(Players, i); afp = false;
                            Console.Write("\nPress T to take the card discarded by {0} or D to draw a card from the pile : ",PrecedentPlayerName); btn = Convert.ToChar(Console.ReadLine());
                            if (btn == 't' || btn == 'T')
                            {
                                this.pickDiscarded(Players, i); break;
                            }
                            else if (btn == 'd' || btn == 'D')
                            {
                                this.drawPile(Players, i); break;
                            }
                            else { throw new FormatException(); }
                            
                        }
                        catch (FormatException)
                        {
                            Console.WriteLine("\nWrong input, you are to enter T or D !\n");
                        }
                    }
                    this.displayDeckNumbered(Players, i); this.discardCard(Players, i); this.checkWinningSuit(Players, i); this.checkDrawGame();
                }
            }
        }
        internal void checkWinningSuit(playingGame[] plyr, int idx)
        {
            int ctr = 0;
            for (int i = 0; i < 4; i++)
            {
                ctr = 0;
                for (int n = 0; n < 5; n++)
                {
                    if (plyr[idx].Deck[n].Contains(CardSuits[i]))
                    {
                        ctr++; 
                        if (ctr == 5) 
                        {
                            Console.WriteLine("\n\n\t !!!!!!! CONGRATULATIONS {0} !!!!!!! \n\t\t !!! YOU ARE THE WINNER !!! ", plyr[idx].Name); this.newGame();
                        }
                    }
                }
            }
        }
        internal void checkDrawGame()
        {
            if (Pile.Count == 0) { Console.WriteLine("\n\n THIS IS A DRAW !!!"); this.newGame(); }
        }
        internal void newGame()
        {
            char ans = 'a';
            while (true)
            {
                try
                {
                    Console.Write("\n\n Would you like to play again (y/n) ? "); ans = Convert.ToChar(Console.ReadLine());
                    if (ans == 'y' || ans == 'Y')
                    {
                        this.setTypes();
                    }
                    if (ans == 'n' || ans == 'N')
                    {
                        Environment.Exit(0);
                    }
                    else { throw new FormatException(); }
                }
                catch (FormatException)
                {
                    Console.Write("\n You are to press y or n ! press a key to continue..."); Console.ReadKey();
                }
            }
        }
    }
}
